<template>
    <!-- 登录注册模块 -->
    <div id="login">
      <div class="l-container">
        <ul class="menu-tab" >
            <!-- for循环 v-for="item in items" :key="item.id"  v-bind:动态绑定一个属性(:) v-on(@)绑定事件 -->
            <li v-for="item in menuTab" :key="item.id" @click="toggleMenu(item)" 
                :class="{'current': item.current}">{{item.txt}}
            </li>
        </ul>
        <!-- 表单 -->
        <!-- v-model数据绑定 在表单控件或者组件上创建双向绑定 -->
        <!--Form表单对象 status-icon 是否在输入框中显示校验结果反馈图标, size用于控制该表单内组件的尺寸, 
            disabled 是否禁用该表单内的所有组件。若设置为 true，则表单内组件上的 disabled 属性不再生效
            rules 表单验证规则
            ref和$refs其实就是用来获取/操作DOM元素的
            ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
            如果在普通的 DOM 元素上使用，引用指向的就是 DOM 元素；如果用在子组件上，引用就指向组件 -->
        <el-form 
            :model="ruleForm"
            :rules="rules"
            status-icon 
            ref="loginForm" 
            class="login-form" 
            size="mini">
            <!--form-item属性  prop 表单域 model 字段，在使用 validate（对整个表单进行校验的方法，参数为一个回调函数。
                该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。
                若不传入回调函数，则会返回一个 promise）、resetFields（对该表单项进行重置，将其值重置为初始值并移除校验结果） 方法的情况下，该属性是必填的
                label 标签文本 
                autocomplete 原生属性，自动补全 -->
            <!-- 邮箱 -->   
            <el-form-item prop="username" class="item-form">
                <label for="">邮箱</label>
                <el-input 
                    type="text"
                    placeholder="输入邮箱" 
                    autocomplete="off"
                    v-model="ruleForm.username" >
                </el-input>
            </el-form-item>
            <!-- 密码 -->
            <el-form-item prop="password" class="item-form">
                <label for="">密码</label>
                <!--type 类型 text，textarea，placeholder 输入框占位文本，autofocus	原生属性，自动获取焦点  -->
                <el-input 
                    type="text" 
                    placeholder="请输入密码" 
                    autocomplete="off" 
                    minlength="6" 
                    maxlength="16"
                    v-model="ruleForm.password" >
                </el-input>
            </el-form-item>
            <!--v-show 无论条件是真假都被编译，然后被缓存，而且DOM元素保留渲染页面结构后，
                通过 "display:none" 控制元素状态，并且在之后一直存在。当切换v-show模块时，只是简单的更改css
                v-if会在切换过程中对条件块的事件监听器和子组件进行销毁和重建，
                如果初始条件是false，则什么都不做，直到条件第一次为true时才开始渲染模块。
                v-show与v-if区别 v-show是利用display隐藏，v-if删除DOM元素，值为true显示 -->
            <!--DOM ducument objest model 文档对象模型
                XML DOM 定义XML的属性和对象，DOM使用来增强网站的动态交互性 
                可通过 JavaScript （以及其他编程语言）对 HTML DOM 进行访问。所有 HTML 元素被定义为对象，而编程接口则是对象方法和对象属性
                DOM方法是我们可以在节点（HTML 元素）上执行的动作、
                DOM属性是我们可以在节点（HTML 元素）设置和修改的值、时间 
                DOM事件(例如onclick) HTML DOM 允许 JavaScript 对 HTML 事件作出反应，当事件发生时，可以执行 JavaScript，比如当用户点击一个 HTML 元素时。
                如需在用户点击某个元素时执行代码，请把 JavaScript 代码添加到 HTML 事件属性中-->
            <!-- 确认密码 -->
            <el-form-item class="item-form" prop="password2" v-show="model==='register'">
                <label for="">确认密码</label>
                <el-input 
                    type="text" 
                    placeholder="请重新再输入密码" 
                    v-model="ruleForm.password2" 
                    autocomplete="off" 
                    minlength="6" 
                    maxlength="16">
                </el-input>
            </el-form-item>
            <!--gutter	栅格间隔， 
                span 栅格占据的列数 -->
            <!-- 验证码 -->
            <el-form-item prop="code" class="item-form">
            <label for="">验证码</label>
                <el-row :gutter="13">
                    <el-col :span="15">
                        <el-input v-model="ruleForm.code" minlength="6" maxlength="6"></el-input>
                    </el-col>
                    <el-col :span="9">
                        <el-button :disabled="codeButtonStatus.status" @click="getSms()" type="success" class="block">
                            {{codeButtonStatus.text}}
                        </el-button>
                    </el-col>
                </el-row>
            </el-form-item>
            <!-- 提交-登录、注册表单 -->
            <el-form-item>
                <el-button @click="submitForm('loginForm')" :disabled="loginButtonStatus" type="danger" class="login-btn block">
                    {{ model==="login" ? "登录" : "注册"}}
                </el-button>
            </el-form-item>
        </el-form>
      </div>
    </div>
</template>

<script>
//sha1加密方式 npm install sha1 --save 
import sha1 from 'js-sha1';
//单独引入 Message
import { Message } from 'element-ui';
//登录接口
import { GetSms ,Register ,Login} from '@/api/login';
//vue3.0 compisitionAPI
import { reactive ,ref , isRef ,toRefs ,onMounted } from '@vue/composition-api'
// @ 配置weboack（vue.config.js）文件, 验证正则表达式
import { stripscript ,validateEmail ,validatePasswd ,validateCoder } from '@/utils/validate'
export default {
    name: 'login',
    /* vue3.0与2.0比较
      attrs: (...) == this.$attrs
      emit: (...) == this.$emit
      listeners: (...) == this.$listeners
      parent: (...) == this.$parent
      refs: (...) == this.$refs
      root: (...) == this
    */
    // setup(props, context){
    setup(props, { refs ,root}){
        // 邮箱
        let validateUsername = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('请输入用户名'));
            } else if(validateEmail(value)){
                callback(new Error('用户名格式有误'));
            } else {
                callback(); //true
            }
        };
      
        // 密码
        let validatePassword = (rule, value, callback) => {
            // 过滤后的数据
            ruleForm.password = stripscript(value);
            value = ruleForm.password;
            if (value === '') {
                callback(new Error("请输入密码"));
            } else if (validatePasswd(value)) {
                callback(new Error("密码为6至20位数字+字母"));
            } else {
                callback();
            }
        };

        // 重复密码
        let validatePassword2 = (rule, value, callback) => {
            // 如果模块值为login, 直接通过
            if(model.value === 'login') { callback(); }
                // 过滤后的数据
                ruleForm.passwords = stripscript(value);
                value = ruleForm.passwords;
            if (value === '') {
                callback(new Error('请再次输入密码'));
            } else if (value != ruleForm.password) {
                callback(new Error('重复密码不正确'));
            } else {
                callback();
            }
        };

        // 验证验证码
        let validateCode = (rule, value, callback) => {
            if (value === '') {
                callback(new Error('请输入验证码'));
            }else if(validateCoder(value)){
                callback(new Error('验证码格式有误'));
            }else{
                callback();
            }
        };

        /******************************************
         * 声明数据
         */
        // 模块值 
        const model = ref('login');
        //倒计时开始
        const timer = ref(null);
        // 登录按钮禁用状态 true为禁用 false接除禁用
        const loginButtonStatus = ref(false);
        // 验证码按钮状态
        // const codeButtonStatus = ref(false);
        // const codeButtonText = ref('获取验证码');
        const codeButtonStatus = reactive ({
            status: false,
            text: '获取验证码'
            //v-model.number 绑定了数字类型输入不了，把number删除
        });
        // 这里面放置data数据、生命周期、自定义的函数
        const menuTab = reactive([
            { txt: '登录', current: true, type: 'login' },
            { txt: '注册', current: false, type: 'register' }
        ]);
        // 表单绑定数据
        const ruleForm = reactive({
            username: '34601620341@qq.com',
            password: 'qqqq1111',
            password2: 'qqqq1111',
            code: ''
        });
        // 表单的验证
        const rules = reactive({
            username: [{ validator: validateUsername, trigger: 'blur' }],
            password: [{ validator: validatePassword, trigger: 'blur' }],
            password2: [{ validator: validatePassword2, trigger: 'blur' }],
            code: [{ validator: validateCode, trigger: 'blur' }]
        });

        //  1、不建议在一个方法里面做多件不同的事件（尽可能只做自己本身的事，不要做其他人的事情）
        //  2、尽量把相同的事情封装一个方法里面，通过调用函数进行执行
        // 声明函数
        // 切换模块
        const toggleMenu = (data => {
            menuTab.forEach((elem, index) => {
                elem.current = false;
            });
            // 高光
            data.current = true;
            // 修改模块值
            model.value = data.type;
            resetFormData();
            clearcountDown();
            
        });
        //封装成一个函数，然后调用 耦合性
        // 清除表单数据
        const resetFormData=(()=>{
            // this.$refs[formName].resetFields(); //2.0
            //清空表单数据
            refs.loginForm.resetFields();
        })
        // 更新按钮状态
        const updataButtonStatus = ((params) =>{
            // params 传入一个对象
            // params = {
            //   status: true,
            //   text: '获取验证码'
            // }
            // params.status = true,
            // params.text = '获取验证码'
            updataButtonStatus.status = params.status;
            updataButtonStatus.text = params.text;
        })
        //获取验证码
        const getSms = ( ( ) => {
            //信息提示
            if(ruleForm.username == ""){
                root.$message.error('邮箱不能为空！');
                return false
            }
            // console.log(validateEmail(ruleForm.username))
            if(validateEmail(ruleForm.username)) {
                root.$message.error('邮箱格式有误，请重新输入！！');
                return false;
            }
            //请求数据
            let requestData = {
                username: ruleForm.username,
                module: model.value,
            }
            //更新状态
            updataButtonStatus({
                status: true,
                text: '发送中'
            })
            // codeButtonStatus.status = true;
            // codeButtonStatus.text = '发送中'
            // 延时时间 setTimeout
            // setTimeout(() => {        
            GetSms( requestData ).then(response =>{
                let data = response.data;
                root.$message({
                    message: data.message,
                    type: 'success'
                })
                loginButtonStatus.value = false;
                // console.log(data)
                countDown(15)
            }).catch(error =>{
                console.log(error)
            })
            // }, 3000)
        })
        // 提交表单
        const submitForm = (formName => {
            //模拟注册        
            // toggleMenu(menuTab[0]) 
            // clearcountDown()       
            // refs.loginForm等同下
            // return false
            refs[formName].validate((valid) => {
                // 表单验证通过
                if (valid) {
                    //三元算法
                    model.value === 'login' ? login():register()
                    // if(model.value==='login'){
                    //   login()
                    // }else{
                    //   register()
                    // }
                    // let requestData = {
                    //   username: ruleForm.username,
                    //   password: ruleForm.password,
                    //   code:ruleForm.code,
                    //   module: 'register'
                    // }
                    // //注册接口
                    // Register(requestData).then(respose =>{
                    //   // console.log(respose)
                    //   let data = respose.data
                    //   root.$message({
                    //     message: data.message,
                    //     type: 'success'
                    //   })
                    //   //模拟注册        
                    //   toggleMenu(menuTab[0]) 
                    //   clearcountDown() 
                    // }).catch(error =>{
                    //   //失败执行的代码
                    // })
                      //alert('submit!');
                } else {
                    console.log('error submit!!');
                    return false;
                }
            });
        }) 
        //登录
        const login = (()=>{
            let requestData = {
                username:ruleForm.username,
                //添加加密方式,前端加密不是很安全，是可以看到的，后台也需要加密
                password:sha1(ruleForm.password),
                code:ruleForm.code
            }
            //调用登录接口 store
            root.$store.dispatch('app/login',requestData).then(response =>{
                console.log('登录成功')
                console.log(response)
                //页面跳转,函数里面调用
                root.$router.push({
                    name: 'Console'
                })
            }).catch(error =>{});
                //登录接口
                // Login(requestData).then(respose =>{
                //   console.log('登录成功')
                //   console.log(requestData)
                //   //页面跳转,函数里面调用
                //   root.$router.push({
                //     name: 'Console'
                //   })
                // }).catch(error =>{
                //   //失败执行的代码
                // })
        });
        //注册
        const register = (()=>{
            let requestData = {
                username: ruleForm.username,
                password: sha1(ruleForm.password),
                code:ruleForm.code,
                module: 'register'
            }
            //注册接口
            Register(requestData).then(respose =>{
                // console.log(respose)
                let data = respose.data
                root.$message({
                    message: data.message,
                    type: 'success'
                })
                //模拟注册,跳转到注册       
                toggleMenu(menuTab[0]) 
                clearcountDown() 
            }).catch(error =>{
                //失败执行的代码
            })
        })
        //倒计时
        const countDown = ((number) =>{
            //0 和 60 故意留个bug，后期处理，测试工程师，禅道
            //只执行一次
            // setTimeout(() => {
            //   console.log('setTimeout')
            // }, 2000);
            //判断定时器是否存在
            if(timer.value){
                clearInterval(timer.value)
            }
            //不断执行，循环执行
            let time = number
            // console.log(time)
            timer.value = setInterval(() => {
                time--;
                //console.log(time)
                if(time === 0){
                    clearInterval(time.value);
                    updataButtonStatus({
                    status: false,
                    text: '再次获取'
                    })
                    // codeButtonStatus.status = false;
                    // codeButtonStatus.text = '再次获取';
                }else{
                    codeButtonStatus.text = `倒计时${time}秒`   //ES6写法 符号
                }
            }, 2000);

        })
        //清除倒计时
        const clearcountDown = (() =>{
            //还原验证码状态
            updataButtonStatus=({
                status: false,
                text: '获取验证码'
            })
            // codeButtonStatus.status = false;
            // codeButtonStatus.text = '获取验证码';
            // const codeButtonStatus = reactive({
            //   status: false,
            //   text: '获取验证码'
            // })
            //清除倒计时状态
            clearInterval(timer.value)
        })

        /**
         * 生命周期
         */
        // 挂载完成后
        onMounted(() => {
            // console.log(process.env.VUE_APP_ABC)
        })

        return {
            toggleMenu,
            model,loginButtonStatus,
            menuTab,ruleForm,rules,
            codeButtonStatus,
            getSms,submitForm,timer,
        }
    }
}
</script>

<style lang="scss" scoped>
#login{
    position: fixed; //static默认定位、absolute绝对定位、fixed相对定位、relative固定定位
    height: 100vh;
    background-image: url('../../assets/images/bgc.jpg');
    width: 100%;
    background-size: cover; //背景图像完全覆盖背景区域
}
.l-container{
     height: 400px;    
    width: 290px;
    margin-top: 10%;
    margin-left: 8%;
    -webkit-box-shadow: 0 0 5px rgba(26, 39, 39, 0.5); //阴影
    -moz-box-shadow: 0 0 5px rgba(26, 39, 39, 0.5);
}
.menu-tab{
    text-align: center;
    padding-top: 3px;
    li{
        display: inline-block;
        width: 66px;
        margin: 0 auto;
        line-height: 23px;
        font-size: 15px;
        color: rgb(0, 0, 0);
        border-radius: 2px;
        cursor: pointer; //鼠标显示
    }
    .current{
     background-color:#FFFFF0;
     }
}
.login-form{
    margin: 0 4px;
    lable{
        display: block;
        margin-bottom: 3px;
        font-size: 12px;
        color: rgb(214, 9, 9);
    }
    .item-form{
        margin-bottom: 13px;
    }
    .block{
        font-size: 12px;
        width: 100%;
    }
    .login-btn{
        margin-top: 13px;
        font-size: 13px;
    }
 }

</style>